#include "gif_show.h"


//http://api.openweathermap.org/data/2.5/weather?q=HangZhou,CN&APPID=258dd1d38777faf216794e0248b6d413
//https://openweathermap.org/注册账号获得的API Key
String openWeatherMapApiKey = "258dd1d38777faf216794e0248b6d413";   //获取天气

String IPforAdressApi = "http://ip-api.com/json/";    //获取城市

const char* apiServer = "http://api.pinduoduo.com/api/server/_stm";   //获取时间


static lv_disp_draw_buf_t draw_buf;  // LVGL显示缓冲区
static lv_color_t buf[width * 20];  // 定义缓冲区大小

unsigned long lastTime = 0;

String jsonBuffer;  

// RTC info
struct timeval tv = {
    .tv_sec = 0,
    .tv_usec = 0,
};
struct tm* timeinfo;

// JSON parsing
static DynamicJsonDocument doc(1024);
// HTTP request
HTTPClient http;

Preferences prefs_1;  //存储时间到nvs区，用于随机函数seed

uint timeforRand = 0;  //随机函数seed

int bootSetFlag = 0;    //用于gif屏显和表情包屏显切换flag
int bootSetFlag1 = 0;
bool bootSetOnceFlag = 0;

bool onceFlag = 1;  //用于存储时间到nvs区，只存储一次flag

unsigned long timerDelay = TimerDelay;

double Temperature = 0;  //温度
double Humidity = 0;   //湿度
double Wind_Speed = 0;    //风速
String weather = "";   //多云/雨天/晴天...

String City = "HangZhou";
String countryCode = "CN";

TFT_eSPI tft;  // TFT显示驱动实例

//lv_obj_t * gif = lv_gif_create(lv_scr_act());
lv_obj_t * gif;  

lv_timer_t *timer_calibrate;
lv_timer_t *timer_clock;

lv_disp_t * my_disp;


static void calibrate_time(time_t epoch_time)   //校准时间
{
  tv.tv_sec = epoch_time;

  setenv("TZ", "CST-8", 1);
  tzset();
  Serial.println("tzset");

  if (settimeofday(&tv, NULL) == 0) {
    ESP_LOGI("RTC Calibration", "RTC time set successfully.");
  } else {
    ESP_LOGE("RTC Calibration", "Failed to set RTC time.");
  }
}

static void ui_time_calibrate(lv_timer_t *timer)    //校准时间函数，联网获取时间
{
  http.begin(apiServer);
  int httpCode = http.GET();
  delay(500);

  if (httpCode == HTTP_CODE_OK) {
    String responseData = http.getString();
    deserializeJson(doc, responseData);

    String time_ms = doc["server_time"];
    long long time_long = atoll(time_ms.c_str());
    time_t current_time = time_long / 1000;
    Serial.println(current_time);

    calibrate_time(current_time);
  } else {
    Serial.println("Failed to retrieve data");
  }

  http.end();
}

static void ui_clock_update(lv_timer_t *timer)    //更新屏显时间函数
{
  gettimeofday(&tv, NULL);

  timeinfo = localtime(&tv.tv_sec);

  // generate time in "HOUR:MINUTE:SECOND" format
  char time_str[9];
  sprintf(time_str, "%02d:%02d:%02d", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
  Serial.println(time_str);

  // generate time in "YYYY/MM/DD" format
  char date_str[11];
  sprintf(date_str, "%04d/%02d/%02d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
  Serial.println(date_str);

  Serial.println("ui_clock_update");

  if(bootSetFlag1 == 1)   //切换到表情包模式，删除屏幕的时间显示
  {
    lv_obj_del(ui_dateLabel);
    lv_obj_del(ui_timeLabel);

    bootSetOnceFlag = 1;
    bootSetFlag1 = 2;
  }

  if(bootSetFlag1 == 0)   //gif屏显模式
  {
    lv_label_set_text_fmt(ui_timeLabel, "%s", time_str);
    lv_label_set_text_fmt(ui_dateLabel, "%s", date_str);
  }

  timeforRand = timeinfo->tm_sec;    //获取变化的时间值之后用于随机函数

  if(onceFlag == 1 && timeinfo->tm_sec > 0 && timeinfo->tm_sec <= 59 && timeinfo->tm_hour > 0 && timeinfo->tm_hour <= 24)   //确定时间已经更新
  {
      prefs_1.begin("timeStored_sec");
      prefs_1.putInt("timeStored_sec", timeinfo->tm_sec);
      prefs_1.begin("timeStored_min");
      prefs_1.putInt("timeStored_min", timeinfo->tm_min);
      prefs_1.end();
      onceFlag = 0;
  }  

}

void ui_timer_init()    //ui界面定时器创建
{
  // calibrate RTC every hour
  timer_calibrate = lv_timer_create(ui_time_calibrate, 60 * 60 * 1000, NULL);
  ui_time_calibrate(timer_calibrate);
  Serial.println("ui_timer_init");

  // refresh time lable every second
  timer_clock = lv_timer_create(ui_clock_update, 1000, NULL);
  ui_clock_update(timer_clock);
}

void Lvgl_Init(uint randomNum)
{
    // 初始化LVGL核心
    lv_init();
    lv_disp_draw_buf_init(&draw_buf, buf, NULL, width * 20);
    
    // 注册显示驱动
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    my_disp = lv_disp_drv_register(&disp_drv);

    ui_init();    //初始化lvgl界面

    // 播放GIF示例
    gif = lv_gif_create(ui_Screen1);
    //srand(timeforRand_min);
    //uint num2 = rand() % 5;  //存储有5个gif
    uint num2 = randomNum % 5;
    Serial.println("num2:");
    Serial.println(num2);
    switch (num2)
    {
        case 0: LV_IMG_DECLARE(ghibli_A); // 声明转换后的GIF数组;
                lv_gif_set_src(gif, &ghibli_A); 
                break;  
        case 1: LV_IMG_DECLARE(ghibli_B); 
                lv_gif_set_src(gif, &ghibli_B); 
                break; 
        case 2: LV_IMG_DECLARE(ghibli_C); 
                lv_gif_set_src(gif, &ghibli_C);
                break;  
        case 3: LV_IMG_DECLARE(ghibli_D); 
                lv_gif_set_src(gif, &ghibli_D);
                break;  
        case 4: LV_IMG_DECLARE(ghibli_E);
                lv_gif_set_src(gif, &ghibli_E); 
                break;  
    }
    lv_img_set_pivot(gif, 0, 0);    
    lv_img_set_zoom(gif, 332);    //缩放，屏幕240*240，gif180*180，缩放倍数等于332/256，我这里不能再放大了，再放大gif不能正常显示了
    //函数试验学习
    //lv_img_set_size_mode(gif, LV_IMG_SIZE_MODE_REAL); 
    //lv_obj_set_pos(gif, 60, 60);
    //lv_obj_align(gif, LV_ALIGN_CENTER, 0, 0);
    //lv_obj_center(gif);

    ui_Screen1_screen_init();   //上面ui_init()好像有问题，我这里又初始化了一下，正常了，初始化lvgl界面

    ui_timer_init();    //定时器初始化
}

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) 
{
  // lvgl屏幕刷新回调函数
  uint32_t w = area->x2 - area->x1 + 1; 
  uint32_t h = area->y2 - area->y1 + 1;
  
  tft.startWrite();
  tft.setAddrWindow(area->x1, area->y1, w, h);
  tft.pushColors((uint16_t*)color_p, w * h, true);
  tft.endWrite();
  
  lv_disp_flush_ready(disp);  // 通知LVGL刷新完成
  Serial.println("屏幕刷新回调函数");

  if(bootSetFlag == 1)      //表情包模式删除天气、城市屏显
  {
      lv_obj_del(ui_locationLabel);
      lv_obj_del(ui_weatherLabel);
      lv_obj_del(ui_temperatureLabel);
      lv_obj_del(ui_humidityLabel);
      lv_obj_del(ui_windSpeedLabel);
      lv_obj_del(ui_temperatureLabel3);
      lv_obj_del(ui_humidityLabel3);
      lv_obj_del(ui_weatherLabel2);
      lv_obj_del(ui_temperatureLabel2);
      lv_obj_del(ui_humidityLabel2);
      lv_obj_del(ui_windSpeedLabel2);

      tft.fillScreen(TFT_BLACK); 

      bootSetOnceFlag = 1;
      bootSetFlag = 2;
  }

  if(bootSetFlag == 0)    //gif屏显，显示天气、地址信息
  {
    lv_label_set_text_fmt(ui_locationLabel, "%s", City);
    lv_label_set_text_fmt(ui_weatherLabel, "%s", "天气：");
    lv_label_set_text_fmt(ui_temperatureLabel, "%s", "温度：");
    lv_label_set_text_fmt(ui_humidityLabel, "%s", "湿度：");
    lv_label_set_text_fmt(ui_windSpeedLabel, "%s", "风速：");
    lv_label_set_text_fmt(ui_temperatureLabel3, "%s", " °C");
    lv_label_set_text_fmt(ui_humidityLabel3, "%s", "%");

    lv_label_set_text_fmt(ui_weatherLabel2, "%s", weather);
    lv_label_set_text_fmt(ui_temperatureLabel2, "%2.0f", Temperature);
    lv_label_set_text_fmt(ui_humidityLabel2, "%2.0f", Humidity);
    lv_label_set_text_fmt(ui_windSpeedLabel2, "%2.0f", Wind_Speed);
  }

}

bool getLocationAndWeather(bool getWeatherFlag)    //通过IP获取地址和天气信息
{
    //发送HTTP获取请求
  if ((millis() - lastTime) > timerDelay)    //获得信息后不再重复获取
  {
    //检测WIFI是否已经连接
    if(WiFi.status()== WL_CONNECTED)
    {

      //将组合好的URL放入httpGETRequest函数中通过HTTP获取请求以获得文本
      jsonBuffer = httpGETRequest(IPforAdressApi.c_str());
      Serial.println(jsonBuffer);

      //将解析的Json对象值储存在Jsonu缓冲区中
      JSONVar myObject = JSON.parse(jsonBuffer);
  
      //判断解析是否成功
      if (JSON.typeof1(myObject) == "undefined") 
      {
        Serial.println("Address Parsing input failed!");
        return getWeatherFlag;
      }
      
      City = JSON.stringify(myObject["city"]) ;
      countryCode = JSON.stringify(myObject["countryCode"]) ;
      //Serial.println(City.length());
      //Serial.println(countryCode.length());
      if(City.length() >= 6 && countryCode.length() == 4)
      {
          Serial.print("City: ");
          //Serial.println(myObject["city"]);
          City.remove(City.length()-1, 1);    // 去掉双引号
          City.remove(0, 1);
          Serial.println(City);

          Serial.print("countryCode: ");
          //Serial.println(myObject["countryCode"]);
          countryCode.remove(countryCode.length()-1, 1);
          countryCode.remove(0, 1);
          Serial.println(countryCode);
      
      String IPforWeatherApi = "http://api.openweathermap.org/data/2.5/weather?q=" + City + "," + countryCode + "&APPID=" + openWeatherMapApiKey;
      Serial.println(IPforWeatherApi);
      
      
      //将组合好的URL放入httpGETRequest函数中通过HTTP获取请求以获得文本
      jsonBuffer = httpGETRequest(IPforWeatherApi.c_str());
      Serial.println(jsonBuffer);

      //将解析的Json对象值储存在Jsonu缓冲区中
      myObject = JSON.parse(jsonBuffer);
  
      //判断解析是否成功
      if (JSON.typeof1(myObject) == "undefined") 
      {
        Serial.println("Weather Parsing input failed!");
        return getWeatherFlag;
      }
      
      Temperature = myObject["main"]["temp"] ;    //myObject["main"]["pressure"]前为{}前的引号内容，后为读取哪一个引号后数据
      Temperature = Temperature-273.15;   //获取到的温度其实是开氏度，开氏度 = 摄氏度+273.15
      Serial.print("Temperature: ");
      Serial.println(Temperature);

      Serial.print("Humidity: ");
      Serial.println(myObject["main"]["humidity"]);
      Humidity = myObject["main"]["humidity"] ;

      Serial.print("Wind Speed: ");
      Serial.println(myObject["wind"]["speed"]);
      Wind_Speed = myObject["wind"]["speed"] ;

      Serial.print("Weather: ");
      //Serial.println(myObject["weather"]["description"]);
      weather = JSON.stringify(myObject["weather"][0]["main"]);    //根据返回json格式填写
      weather.remove(weather.length()-1, 1);    // 去掉双引号
      weather.remove(0, 1);
      Serial.println(weather);

      }

    }       
    
    else 
    {
      Serial.println("WiFi Disconnected");
    }

    lastTime = millis();

    if(Temperature <= 50 && Temperature >= -50 && Humidity > 0 && Humidity <= 100 && Wind_Speed >= 0 && Wind_Speed <= 18)    //确认获得了地址和天气信息
    {
        getWeatherFlag = 1;

    }

  }
  return getWeatherFlag;
}

String httpGETRequest(const char* serverName)   //联网通过http获取数据
{
  WiFiClient client;
  HTTPClient http;
    
  //连接网址
  http.begin(client, serverName);
  
  //发送HTTP站点请求
  int httpResponseCode = http.GET();

  //该数组用于储存获得的数据
  String payload = "{}";
  
  //将获得的数据放入数组
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  
  //释放资源
  http.end();
  
  //返回获得的数据用于Json处理
  return payload;
}

void CuteEyesGif()      //表情模式
{
    Serial.print("boot on......");
    if(bootSetOnceFlag == 0)
    {
      bootSetFlag = 1;
      bootSetFlag1 = 1;
    }
    //lv_obj_t * gif1 = lv_gif_create(lv_scr_act());
    //srand(timeforRand2);
    Serial.print("timeforRand:");
    Serial.println(timeforRand);
    uint num3 = timeforRand % 3;
    //uint num3 = rand() % 3;
    Serial.println("num3:");
    Serial.println(num3);
    switch (num3)
    {
        case 0: LV_IMG_DECLARE(robot_facial18); 
            lv_gif_set_src(gif, &robot_facial18); 
            break; 
        case 1: LV_IMG_DECLARE(robot_facial28); 
            lv_gif_set_src(gif, &robot_facial28);
            break;  
        case 2: LV_IMG_DECLARE(robot_facial38); 
            lv_gif_set_src(gif, &robot_facial38);
            break;  
    //case 3: LV_IMG_DECLARE(robot_facial4);
            //lv_gif_set_src(gif, &robot_facial4); 
            //break;  
    }
    lv_img_set_pivot(gif, 0, 0);
    lv_img_set_zoom(gif, 330);
}





